package com.htfyun.eink.pw.core;

import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * 在 PW JNI 里, 维护着 2个 bmp(从外部传入), 分别是:<br>
 * 1. 手写 BMP: 有笔迹的地方是黑色,没有笔迹的地方是透明;<br>
 * 2. HOST-BMP: 比如擦除或者FLOAT类型的显示BITMAP, 这个bitmap的 alpha 都是不透明的.<br>
 */
public interface IEinkPWCoreController {

    /**
     * 初始化
     */
    void initForPw();

    /**
     * 反初始化
     */
    void deinitForPw();

    /**
     * 更新 dirty 区域. <br>
     * 为了加快手写显示, 每次只需要更新 '新画' 的那部分 rect.
     *
     * @param dirty       需要更新的那部分 rect
     * @param bmpType     更新的 bmp type <br>
     *                    BMP_TYPE_PW(0) //手写BMP(有笔迹的地方是黑色，没有笔迹的地方是透明) <br>
     *                    BMP_TYPE_HOST(1) //HOST-BMP，比如擦除或者FLOAT类型的显示BITMAP.这个bitmap的 alpha 都是不透明的 <br>
     * @param displayMode 显示模式 <br>
     *                    EINKMODE_GLAUTO(7),<br>
     *                    EINKMODE_FAUTO(5),// 20201217: 我们用来做MARK笔显示灰阶<br>
     *                    EINKMODE_DUAUTO(16),<br>
     *                    EINKMODE_GLUI(3),// View.EINK_SHOW_MODE_GL<br>
     * @param dataMode    数据模式 <br>
     *                    EinkDataModeA16(3),// 有灰阶 <br>
     *                    EinkDataModeA2(1),// 只有黑白 <br>
     * @param a2Gate      如果 {@param dataMode}  是 A16, gate 就是锐化等级。如果没有锐化，需要设置为 0XFF.
     *                    EinkA2GateForA16(0),
     *                    EinkA2GateForDUAUTO(0xB7),
     */
    void postRectForPw(@NonNull Rect dirty, int bmpType, int displayMode, int dataMode, int a2Gate);

    /**
     * 旋转 bmp <br>
     * 在 PW JNI 里, 操作的总是物理屏. 而物理屏和实际显示的方向不一致. 可以通过 dumpsys SurfaceFlinger
     * 查看 Display[0] configurations 来看实际物理屏方向
     *
     * @param rotation      {@link android.view.Display#getRotation()}*90 + {@link #getHWRotation()}
     * @param displayWidth  {@link android.view.Display#getRealSize(Point)} 返回的 width
     * @param displayHeight {@link android.view.Display#getRealSize(Point)} 返回的 height
     */
    void updatePwCanvasRotation(int rotation, int displayWidth, int displayHeight);

    /**
     * rk3566(android11) 是通过 ro.surface_flinger.primary_display_orientation 获取 <br>
     * px30s(android8.1) 是通过 ro.sf.hwrotation 获取 <br>
     *
     * @return 屏幕的实际旋转角度
     */
    int getHWRotation();

    /**
     * @param bmp     手写 BMP
     * @param offsetX 相对屏幕的 X 偏移量
     * @param offsetY 相对屏幕的 Y 偏移量
     */
    void setPWViewOffsetXY(@NonNull Bitmap bmp, int offsetX, int offsetY);

    /**
     * @param bmp     HOST-BMP
     * @param offsetX 相对屏幕的 X 偏移量
     * @param offsetY 相对屏幕的 Y 偏移量
     */
    void setHostBmpOffsetXY(@NonNull Bitmap bmp, int offsetX, int offsetY);

    /**
     * 更新手写属性. 暂时不需要.
     */
    void updatePWProperty();

    /**
     * 设置手写 action
     */
    void setPWAction(int action);

    /**
     * 设置 pointer event 监听
     *
     * @param view     要监听 的那个 View
     * @param listener 监听回调
     */
    void setPointerEventListenerForView(@Nullable View view, @Nullable IPointerEventListener listener);

    /**
     * 设置 onDraw 监听
     *
     * @param view     要监听的那个 View
     * @param listener 监听回调
     */
    void setOnDrawListenerForView(@Nullable View view, @Nullable IOnDrawListener listener);

    /////////////////////////////////
    // 以下方法 跟 pw 底层无关

    /**
     * 注册 IImeStateListener
     *
     * @param listener {@link IImeStateListener}
     */
    void registerImeStateListener(@NonNull IImeStateListener listener);

    /**
     * 移除注册 IImeStateListener
     *
     * @param listener {@link IImeStateListener}
     */
    void unregisterImeStateListener(@NonNull IImeStateListener listener);

    /**
     * 设置 view 数据模式和显示模式
     *
     * @param view     需要设置的 view
     * @param dataMode 数据模式
     * @param dispMode 显示模式
     */
    void setEinkUpdateModeWithView(@NonNull View view, int dataMode, int dispMode);

    /**
     * 调用 {@link android.animation.ValueAnimator#setDurationScale(float)}
     */
    void setValueAnimatorDurationScale(float durationScale);

    /**
     * Get the value for the given key.
     *
     * @return an empty string if the key isn't found
     */
    @NonNull
    String getSystemProperties(String key);

    /**
     * Set the value for the given key.
     *
     * @throws IllegalArgumentException if the value exceeds 92 characters
     */
    void setSystemProperties(String key, String val);

    // 以上方法 跟 pw 底层无关
    /////////////////////////////////
}
